<?php
/**
 * 商品价格缓存服务
 * 作者: 王勇程 (laughskydragon@qq.com)
 */

namespace app\common\service;

use think\facade\Cache;
use think\facade\Log;

class PriceCache extends ServiceBase implements BaseInterface
{
    // 缓存前缀
    const CACHE_PREFIX = 'price_cache:';
    
    // 缓存时间（秒）
    const CACHE_TIME = 3600; // 1小时
    
    // 文件缓存目录
    const CACHE_DIR = 'cache/price/';
    
    /**
     * 服务基本信息
     */
    public function serviceInfo()
    {
        return [
            'service_name' => '价格缓存服务', 
            'service_class' => 'PriceCache', 
            'service_describe' => '商品价格缓存服务，用于缓存商品价格数据和统计信息', 
            'author' => '王勇程', 
            'version' => '1.0'
        ];
    }
    
    /**
     * 获取商品价格缓存
     */
    public static function getProductPrice($productId)
    {
        $cacheKey = self::CACHE_PREFIX . 'product:' . $productId;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('product_' . $productId);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return false;
    }
    
    /**
     * 设置商品价格缓存
     */
    public static function setProductPrice($productId, $priceData)
    {
        $cacheKey = self::CACHE_PREFIX . 'product:' . $productId;
        
        // 设置内存缓存
        Cache::set($cacheKey, $priceData, self::CACHE_TIME);
        
        // 设置文件缓存
        self::setToFileCache('product_' . $productId, $priceData);
        
        return true;
    }
    
    /**
     * 获取商品价格历史缓存
     */
    public static function getProductHistory($productId, $days = 30)
    {
        $cacheKey = self::CACHE_PREFIX . 'history:' . $productId . ':' . $days;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('history_' . $productId . '_' . $days);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return false;
    }
    
    /**
     * 设置商品价格历史缓存
     */
    public static function setProductHistory($productId, $days, $historyData)
    {
        $cacheKey = self::CACHE_PREFIX . 'history:' . $productId . ':' . $days;
        
        // 设置内存缓存
        Cache::set($cacheKey, $historyData, self::CACHE_TIME);
        
        // 设置文件缓存
        self::setToFileCache('history_' . $productId . '_' . $days, $historyData);
        
        return true;
    }
    

    
    /**
     * 获取价格统计缓存
     */
    public static function getPriceStatistics($type = 'daily')
    {
        $cacheKey = self::CACHE_PREFIX . 'stats:' . $type;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('stats_' . $type);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return false;
    }
    
    /**
     * 设置价格统计缓存
     */
    public static function setPriceStatistics($type, $statsData)
    {
        $cacheKey = self::CACHE_PREFIX . 'stats:' . $type;
        
        // 设置内存缓存
        Cache::set($cacheKey, $statsData, self::CACHE_TIME);
        
        // 设置文件缓存
        self::setToFileCache('stats_' . $type, $statsData);
        
        return true;
    }
    
    /**
     * 清除商品价格缓存
     */
    public static function clearProductPrice($productId)
    {
        // 清除内存缓存
        $cacheKey = self::CACHE_PREFIX . 'product:' . $productId;
        Cache::delete($cacheKey);
        
        // 清除文件缓存
        self::deleteFileCache('product_' . $productId);
        
        // 清除相关历史缓存
        $historyKeys = [7, 15, 30, 90];
        foreach ($historyKeys as $days) {
            $historyCacheKey = self::CACHE_PREFIX . 'history:' . $productId . ':' . $days;
            Cache::delete($historyCacheKey);
            self::deleteFileCache('history_' . $productId . '_' . $days);
        }
        
        // 清除价格趋势缓存
        $trendPeriods = ['7d', '30d', '90d'];
        foreach ($trendPeriods as $period) {
            $trendCacheKey = "price_trend_{$productId}_{$period}";
            Cache::delete($trendCacheKey);
            
            // 也清除PriceCache的趋势缓存
            $priceCacheTrendKey = self::CACHE_PREFIX . 'trend:' . $productId . ':' . $period;
            Cache::delete($priceCacheTrendKey);
            self::deleteFileCache('trend_' . $productId . '_' . $period);
        }
        
        // 清除价格统计缓存
        $statsDays = [7, 30, 90];
        foreach ($statsDays as $days) {
            $statsCacheKey = self::CACHE_PREFIX . 'stats:' . $productId . ':' . $days;
            Cache::delete($statsCacheKey);
            self::deleteFileCache('stats_' . $productId . '_' . $days);
        }
        
        \think\facade\Log::record("清除商品价格缓存: productId={$productId}", 'info');
        
        return true;
    }
    
    /**
     * 清除所有价格缓存
     */
    public static function clearAllPriceCache()
    {
        // 清除内存缓存
        Cache::clear();
        
        // 清除文件缓存目录
        $cacheDir = \think\facade\App::getInstance()->getRuntimePath() . self::CACHE_DIR;
        if (is_dir($cacheDir)) {
            self::deleteDirectory($cacheDir);
        }
        
        return true;
    }
    
    /**
     * 从文件缓存获取数据
     */
    private static function getFromFileCache($key)
    {
        $cacheFile = self::getCacheFilePath($key);
        
        if (!file_exists($cacheFile)) {
            return false;
        }
        
        $content = file_get_contents($cacheFile);
        if ($content === false) {
            return false;
        }
        
        $data = json_decode($content, true);
        if (!$data || !isset($data['expire_time']) || !isset($data['data'])) {
            return false;
        }
        
        // 检查是否过期
        if ($data['expire_time'] > 0 && time() > $data['expire_time']) {
            self::deleteFileCache($key);
            return false;
        }
        
        return $data['data'];
    }
    
    /**
     * 设置文件缓存
     */
    private static function setToFileCache($key, $data, $expireTime = null)
    {
        $cacheFile = self::getCacheFilePath($key);
        $cacheDir = dirname($cacheFile);
        
        // 创建缓存目录
        if (!is_dir($cacheDir)) {
            mkdir($cacheDir, 0755, true);
        }
        
        $expireTime = $expireTime ?: (time() + self::CACHE_TIME);
        
        $cacheData = [
            'data' => $data,
            'expire_time' => $expireTime,
            'create_time' => time()
        ];
        
        $result = file_put_contents($cacheFile, json_encode($cacheData, JSON_UNESCAPED_UNICODE));
        
        if ($result === false) {
            Log::error('文件缓存写入失败', ['file' => $cacheFile]);
            return false;
        }
        
        return true;
    }
    
    /**
     * 删除文件缓存
     */
    private static function deleteFileCache($key)
    {
        $cacheFile = self::getCacheFilePath($key);
        
        if (file_exists($cacheFile)) {
            return unlink($cacheFile);
        }
        
        return true;
    }
    
    /**
     * 获取缓存文件路径
     */
    private static function getCacheFilePath($key)
    {
        $cacheDir = \think\facade\App::getInstance()->getRuntimePath() . self::CACHE_DIR;
        return $cacheDir . md5($key) . '.cache';
    }
    
    /**
     * 删除目录及其内容
     */
    private static function deleteDirectory($dir)
    {
        if (!is_dir($dir)) {
            return false;
        }
        
        $files = array_diff(scandir($dir), ['.', '..']);
        
        foreach ($files as $file) {
            $filePath = $dir . DIRECTORY_SEPARATOR . $file;
            if (is_dir($filePath)) {
                self::deleteDirectory($filePath);
            } else {
                unlink($filePath);
            }
        }
        
        return rmdir($dir);
    }
    
    /**
     * 获取缓存统计信息
     */
    public static function getCacheStats()
    {
        $cacheDir = \think\facade\App::getInstance()->getRuntimePath() . self::CACHE_DIR;
        $stats = [
            'total_files' => 0,
            'total_size' => 0,
            'expired_files' => 0,
            'valid_files' => 0,
            // 兼容 admin 模板期望的键名
            'total_count' => 0,
            'valid_count' => 0,
            'expired_count' => 0,
            'price_cache_size' => '0KB',
            'cache_size' => '0KB',
            // 辅助信息
            'cache_time' => self::CACHE_TIME,
            'cache_dir' => $cacheDir,
            'last_update' => 0,
        ];

        if (!is_dir($cacheDir)) {
            return $stats;
        }

        $files = glob($cacheDir . '*');
        $latestMtime = 0;

        foreach ($files as $file) {
            if (!is_file($file)) { continue; }
            $size = @filesize($file) ?: 0;
            $stats['total_size'] += $size;

            $mtime = @filemtime($file) ?: 0;
            if ($mtime > $latestMtime) {
                $latestMtime = $mtime;
            }

            $content = @file_get_contents($file);
            $data = $content ? json_decode($content, true) : null;

            if (is_array($data) && array_key_exists('expire_time', $data)) {
                if ($data['expire_time'] > 0 && time() > $data['expire_time']) {
                    $stats['expired_files']++;
                } else {
                    $stats['valid_files']++;
                }
            }
        }

        $stats['total_files'] = count(array_filter($files, 'is_file'));
        $stats['total_count'] = $stats['total_files'];
        $stats['valid_count'] = $stats['valid_files'];
        $stats['expired_count'] = $stats['expired_files'];
        $stats['last_update'] = $latestMtime;

        // 人类可读的大小字符串
        $size = $stats['total_size'];
        if ($size >= 1024 * 1024 * 1024) {
            $stats['price_cache_size'] = round($size / (1024 * 1024 * 1024), 2) . 'GB';
        } elseif ($size >= 1024 * 1024) {
            $stats['price_cache_size'] = round($size / (1024 * 1024), 2) . 'MB';
        } elseif ($size >= 1024) {
            $stats['price_cache_size'] = round($size / 1024, 2) . 'KB';
        } else {
            $stats['price_cache_size'] = $size . 'B';
        }
        $stats['cache_size'] = $stats['price_cache_size'];

        return $stats;
    }
    
    /**
     * 清理过期缓存
     */
    public static function cleanExpiredCache()
    {
        $cacheDir = \think\facade\App::getInstance()->getRuntimePath() . self::CACHE_DIR;
        $cleanedCount = 0;
        
        if (!is_dir($cacheDir)) {
            return $cleanedCount;
        }
        
        $files = glob($cacheDir . '*.cache');
        
        foreach ($files as $file) {
            $content = file_get_contents($file);
            $data = json_decode($content, true);
            
            if ($data && isset($data['expire_time'])) {
                if ($data['expire_time'] > 0 && time() > $data['expire_time']) {
                    if (unlink($file)) {
                        $cleanedCount++;
                    }
                }
            }
        }
        
        return $cleanedCount;
    }
    
    /**
     * 获取缓存的价格趋势数据
     */
    public static function getCachedPriceTrend($productId, $period = '30d')
    {
        $cacheKey = self::CACHE_PREFIX . 'trend:' . $productId . ':' . $period;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('trend_' . $productId . '_' . $period);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return null;
    }
    
    /**
     * 缓存价格趋势数据
     */
    public static function cachePriceTrend($productId, $period, $trendData, $expireTime = null)
    {
        $cacheKey = self::CACHE_PREFIX . 'trend:' . $productId . ':' . $period;
        
        $expireTime = $expireTime ?: self::CACHE_TIME;
        
        // 设置内存缓存
        Cache::set($cacheKey, $trendData, $expireTime);
        
        // 设置文件缓存
        self::setToFileCache('trend_' . $productId . '_' . $period, $trendData, time() + $expireTime);
        
        return true;
    }
    
    /**
     * 获取缓存的价格列表
     */
    public static function getCachedPriceList($cacheKey)
    {
        $fullCacheKey = self::CACHE_PREFIX . 'list:' . $cacheKey;
        
        // 先从内存缓存获取
        $data = Cache::get($fullCacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('list_' . $cacheKey);
        if ($data !== false) {
            // 重新设置内存缓存（列表缓存时间较短）
            Cache::set($fullCacheKey, $data, 600); // 10分钟
            return $data;
        }
        
        return null;
    }
    
    /**
     * 缓存价格列表
     */
    public static function cachePriceList($cacheKey, $listData, $expireTime = 600)
    {
        $fullCacheKey = self::CACHE_PREFIX . 'list:' . $cacheKey;
        
        // 设置内存缓存
        Cache::set($fullCacheKey, $listData, $expireTime);
        
        // 设置文件缓存
        self::setToFileCache('list_' . $cacheKey, $listData, time() + $expireTime);
        
        return true;
    }
    
    /**
     * 获取缓存的价格统计
     */
    public static function getCachedPriceStats($productId, $days)
    {
        $cacheKey = self::CACHE_PREFIX . 'stats:' . $productId . ':' . $days;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('stats_' . $productId . '_' . $days);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return null;
    }
    
    /**
     * 缓存价格统计
     */
    public static function cachePriceStats($productId, $days, $statsData, $expireTime = null)
    {
        $cacheKey = self::CACHE_PREFIX . 'stats:' . $productId . ':' . $days;
        
        $expireTime = $expireTime ?: self::CACHE_TIME;
        
        // 设置内存缓存
        Cache::set($cacheKey, $statsData, $expireTime);
        
        // 设置文件缓存
        self::setToFileCache('stats_' . $productId . '_' . $days, $statsData, time() + $expireTime);
        
        return true;
    }
    
    /**
     * 获取商品列表价格缓存
     */
    public static function getProductListPrice($page, $limit, $categoryId, $sort)
    {
        $cacheKey = self::CACHE_PREFIX . 'list:' . $page . ':' . $limit . ':' . $categoryId . ':' . $sort;
        
        // 先从内存缓存获取
        $data = Cache::get($cacheKey);
        if ($data !== false) {
            return $data;
        }
        
        // 从文件缓存获取
        $data = self::getFromFileCache('list_' . $page . '_' . $limit . '_' . $categoryId . '_' . $sort);
        if ($data !== false) {
            // 重新设置内存缓存
            Cache::set($cacheKey, $data, self::CACHE_TIME);
            return $data;
        }
        
        return false;
    }
    
    /**
     * 设置商品列表价格缓存
     */
    public static function setProductListPrice($page, $limit, $categoryId, $sort, $listData)
    {
        $cacheKey = self::CACHE_PREFIX . 'list:' . $page . ':' . $limit . ':' . $categoryId . ':' . $sort;
        
        // 设置内存缓存
        Cache::set($cacheKey, $listData, self::CACHE_TIME);
        
        // 设置文件缓存
        self::setToFileCache('list_' . $page . '_' . $limit . '_' . $categoryId . '_' . $sort, $listData);
        
        return true;
    }
}